﻿#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <iostream>
#include <math.h>

using namespace std;

#define BLOCK_SIZE 20
#define HEIGHT 35
#define WIDTH 45

int g_blocks[HEIGHT][WIDTH] = { 0 };
char move_diretion;
int food_i;
int food_j;
int failure = 0;
int score = 0;


void print_score(int, int);


void startup()
{

	g_blocks[HEIGHT / 2][WIDTH / 2] = 1;

	int initial_length = 5;

	for (int i = 1; i < initial_length; i++)
	{
		g_blocks[HEIGHT / 2][WIDTH / 2 - i] = 1 + i;
	}
	move_diretion = 'd';
	food_i = rand() % (HEIGHT - 5) + 2;
	food_j = rand() % (WIDTH - 5) + 2;
	initgraph(WIDTH * BLOCK_SIZE, HEIGHT * BLOCK_SIZE);
	setlinecolor(RGB(200, 200, 200));
	BeginBatchDraw();
}


void show()
{
	cleardevice();

	for (int i = 0; i < HEIGHT; i++)
	{
		for (int j = 0; j < WIDTH; j++)
		{
			// Draw snake's body.
			if (g_blocks[i][j] > 0)
			{
				setfillcolor(HSVtoRGB(g_blocks[i][j] * 10, 0.9, 1));

			}
			else
			{
				setfillcolor(LIGHTGRAY);
			}

			fillrectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE);
		}
	}
	//Draw food.
	setfillcolor(GREEN);
	fillrectangle(food_j * BLOCK_SIZE, food_i * BLOCK_SIZE, (food_j + 1) * BLOCK_SIZE, (food_i + 1) * BLOCK_SIZE);

	if (failure)
	{
		//setbkcolor(TRANSPARENT);
		setbkcolor(LIGHTGRAY);
		settextcolor(RED);
		settextstyle(80, 0, _T("楷体"));
		outtextxy(300, 250, _T("游戏失败"));
	}

	print_score(40, 10);
	FlushBatchDraw();
}


void move_snake()
{
	for (int i = 0; i < HEIGHT; i++)
	{
		for (int j = 0; j < WIDTH; j++)
		{
			if (g_blocks[i][j] > 0)
			{
				g_blocks[i][j]++;
			}
		}
	}
	int old_tail_i, old_tail_j, old_head_i, old_head_j;
	int max = 0;
	for (int i = 0; i < HEIGHT; i++)
	{
		for (int j = 0; j < WIDTH; j++)
		{
			if (max < g_blocks[i][j])
			{
				max = g_blocks[i][j];
				old_tail_i = i;
				old_tail_j = j;
			}
			if (g_blocks[i][j] == 2)
			{
				old_head_i = i;
				old_head_j = j;
			}
		}
	}
	int new_head_i = old_head_i;
	int new_head_j = old_head_j;

	if (move_diretion == 'w')
	{
		new_head_i = old_head_i - 1;
	}
	else if (move_diretion == 's')
	{
		new_head_i = old_head_i + 1;
	}
	else if (move_diretion == 'a')
	{
		new_head_j = old_head_j - 1;
	}
	else if (move_diretion == 'd')
	{
		new_head_j = old_head_j + 1;
	}

	if (new_head_i >= HEIGHT || new_head_i < 0 || new_head_j >= WIDTH || new_head_j < 0 || g_blocks[new_head_i][new_head_j])
	{
		failure = 1;
		return;
	}
	g_blocks[new_head_i][new_head_j] = 1;
	if (new_head_i == food_i && new_head_j == food_j)
	{
		score += 1;
		food_i = rand() % (HEIGHT - 5) + 2;
		food_j = rand() % (WIDTH - 5) + 2;
	}
	else
	{
		g_blocks[old_tail_i][old_tail_j] = 0;
	}
}


void print_score(int x, int y)
{
	TCHAR text[20];
	swprintf_s(text, _T("%d"), score);
	setbkcolor(LIGHTGRAY);
	settextcolor(BLACK);
	settextstyle(40, 0, _T("楷体"));
	outtextxy(x, y, text);
}


void update_without_input()
{
	if (failure)
	{
		return;
	}
	static int wait_index = 1;
	wait_index++;
	if (wait_index == 30)
	{
		move_snake();
		wait_index = 1;
	}
}


void update_with_input()
{
	if (_kbhit() && failure == 0)
	{
		char input = _getch();
		if (input == 'a' || input == 's' || input == 'd' || input == 'w')
		{
			move_diretion = input;
			move_snake();
		}
	}
}


int main()
{
	startup();

	while (1)
	{
		show();
		update_without_input();
		update_with_input();

		if (failure)
		{
			//setbkcolor(TRANSPARENT);
			setbkcolor(LIGHTGRAY);
			settextcolor(RED);
			settextstyle(80, 0, _T("楷体"));
			outtextxy(300, 250, _T("游戏失败"));
			if (_kbhit)
			{
				char input = _getch();
				if (input == ' ')
				{
					break;
				}
			}
		}
		
	}
	return 0;
}